<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>Document</title>
    <style>
      .box {
        width: 500px;
        height: 400px;
        border: 1px solid #000;
        position: relative;
      }
      .item {
        position: absolute;
        top: 0;
        right: 100px;
        width: 60px;
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <canvas
        id="canvas"
        width="500"
        height="400"
        style="background-color: #f5f5f5"
      ></canvas>
      <div class="item">
        <div>你好</div>
        <div>优秀</div>
        <div>实力</div>
      </div>
    </div>
    <script>
      class HiDPICanvas {
        constructor(canvas) {
          this.canvas = canvas
          this.ctx = canvas.getContext('2d')
          this.resizeHandler = this.resizeHandler.bind(this)

          this.updateSize()
          window.addEventListener('resize', this.resizeHandler)
        }

        updateSize() {
          const dpr = window.devicePixelRatio || 1
          const rect = this.canvas.getBoundingClientRect()

          this.canvas.width = rect.width * dpr
          this.canvas.height = rect.height * dpr

          this.ctx.scale(dpr, dpr)

          this.canvas.style.width = `${rect.width}px`
          this.canvas.style.height = `${rect.height}px`
        }

        resizeHandler() {
          this.updateSize()
          this.redraw()
        }

        redraw() {
          // 清空画布
          this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)

          // 子类可以重写此方法来定义绘制逻辑
          this.draw()
        }

        draw() {
          // 默认绘制示例
          this.ctx.fillRect(10, 10, 100, 100)
        }

        drawRoundedRect(x, y, width, height, radius) {
          this.ctx.beginPath()
          // 绘制四个角的圆弧和连接线
          this.ctx.arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0) // 右上角
          this.ctx.arc(
            x + width - radius,
            y + height - radius,
            radius,
            0,
            Math.PI / 2
          ) // 右下角
          this.ctx.arc(
            x + radius,
            y + height - radius,
            radius,
            Math.PI / 2,
            Math.PI
          ) // 左下角
          this.ctx.arc(
            x + radius,
            y + radius,
            radius,
            Math.PI,
            (Math.PI * 3) / 2
          ) // 左上角
          this.ctx.closePath()
          // 填充或描边
          this.ctx.fill()
        }

        destroy() {
          window.removeEventListener('resize', this.resizeHandler)
        }
      }

      // 使用示例
      const hiDPICanvas = new HiDPICanvas(document.getElementById('canvas'))

      // 自定义绘制逻辑
      hiDPICanvas.draw = function () {
        this.ctx.translate(150, 200)
        this.ctx.save()
        this.ctx.rotate((Math.PI / 180) * 120)
        this.ctx.beginPath()
        this.ctx.arc(0, 0, 80, 0, 300 * (Math.PI / 180))
        this.ctx.lineCap = 'round'
        this.ctx.lineWidth = 20
        this.ctx.strokeStyle = 'rgba(0, 0, 0, 0.16)'
        this.ctx.stroke()
        this.ctx.closePath()
        this.ctx.beginPath()
        this.ctx.arc(0, 0, 80, 0, 120 * (Math.PI / 180))
        this.ctx.lineCap = 'round'
        this.ctx.lineWidth = 20
        this.ctx.strokeStyle = '#f00'
        this.ctx.stroke()
        this.ctx.closePath()
        this.ctx.restore()
        this.ctx.beginPath()
        this.ctx.fillStyle = '#f00'
        this.ctx.font = '18px Arial'
        let str = '60%'
        const metrics = this.ctx.measureText(str)
        this.ctx.fillText(str, -metrics.width / 2, 0)
        this.ctx.closePath()
        this.ctx.fillStyle = 'rgba(0, 0, 0, 0.3)'
        this.drawRoundedRect(-20, 70, 40, 16, 4)
        this.ctx.fillStyle = '#fff'
        this.ctx.font = '12px Arial'
        let str1 = 'hello'
        this.ctx.fillText(str1, -this.ctx.measureText(str1).width / 2, 82)
      }

      hiDPICanvas.draw()
    </script>
  </body>
</html>
